package com.czl.myRabbitMq.mqServer.core;

import com.czl.myRabbitMq.commom.ConsumeEnv;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.*;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Data
@ToString
//队列
public class MSGQueue {
    private String name;
    //交换机是否可持久化
    private boolean durable = false;

    //设置为false后该消息队列能被消费者共同使用，true时该消息队列只能被一个消费者使用
    private boolean exclusive;

    //当前交换机没人使用后是否自动删除
    private boolean isAutoDelete = false;
    //创建交换机时其他选项

    //表示这个队列有哪些消费者进行消费
    private List<ConsumeEnv> consumeEnvList = new ArrayList<>();
    //为轮询查询增加一个变量 来记录当前消息取到什么地方来了 因为涉及到多线程操作
    @Setter(AccessLevel.NONE)
    @Getter(AccessLevel.NONE)
    private AtomicInteger consumeIndex = new AtomicInteger(0);

    //不为这个字段创建get和set方法
    //本项目使用的数据库为sqlite 但是sqlite中不支持存储键值对形式的数据。所以在存储map类型的数据时，先将数据进行json格式的字符串转化。
    @Setter(AccessLevel.NONE)
    @Getter(AccessLevel.NONE)
    private Map<String,Object> params = new HashMap<>();


    //为队列添加一个消费者
    public void addConsumeEnv(ConsumeEnv consumeEnv){
        synchronized (this) {
            consumeEnvList.add(consumeEnv);
        }
    }

    //目前使用轮询策略 查询出当前该轮到那个消费者取消息了
    public ConsumeEnv chooseConsume(){
        if(consumeEnvList.size() == 0){//表示当前队列中没有消息
            return null;
        }
        int index = consumeIndex.get() % consumeEnvList.size();
        ConsumeEnv consumeEnv = consumeEnvList.get(index);
        //将原子类自增1的操作
        consumeIndex.getAndIncrement();
        return consumeEnv;
    }
    /**
     mybatis在向数据库调用CRUD的方法时，会调用属性的get和set方法因为数据
     库不支持直接存储map类型 所以这里我们将数据先转化为json格式的字符粗后，
     在进行统一的处理。 转化方式为改写该属性的get和set方法
     */

    public String getParams() {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String params = objectMapper.writeValueAsString(this.params);
            return params;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        //要是出现了异常则返回一个空的json格式的数据过去

    }
    //set方法是先从数据库里面取出数据在调用set方法
    public void setParams(String params){
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            //注意此处的TypeReference是一个抽象方法 下面代码中必须要写{}(匿名内部类的一种写法)
            this.params = objectMapper.readValue(params, new TypeReference<HashMap<String , Object>>(){});
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    public void setParams(Map<String, Object> params){
        this.params = params;
    }

    public Object testGetParams(String key){
        return this.params.get(key);
    }

    public void testSetParams(String key, Object value){
        this.params.put(key,value);
    }
}
